<!--

    Copyright © 2016-2025 The Thingsboard Authors

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<div>
  <mat-card appearance="outlined" class="settings-card">
    <mat-card-header>
      <mat-card-title>
        <span class="mat-headline-5" translate>admin.2fa.2fa</span>
      </mat-card-title>
      <span class="flex-1"></span>
      <div tb-help="twoFactorAuthentication"></div>
    </mat-card-header>
    <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
    </mat-progress-bar>
    <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
    <mat-card-content>
      <form [formGroup]="twoFaFormGroup" (ngSubmit)="save()">
        <fieldset [disabled]="isLoading$ | async">
          <div class="tb-form-panel no-padding no-border">
            <div class="tb-form-panel stroked tb-slide-toggle">
              <mat-expansion-panel class="tb-settings no-padding-bottom">
                <mat-expansion-panel-header>
                  <mat-panel-title>
                    <mat-slide-toggle class="mat-slide flex items-center justify-start"
                                      (mousedown)="toggleExtensionPanel($event, 0, twoFaFormGroup.get('enforceTwoFa').value)"
                                      formControlName="enforceTwoFa">
                      {{ 'admin.2fa.force-2fa' | translate }}
                    </mat-slide-toggle>
                  </mat-panel-title>
                </mat-expansion-panel-header>
                <ng-template matExpansionPanelContent>
                  <section class="tb-form-panel no-padding no-border" formGroupName="enforcedUsersFilter">
                    <mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
                      <mat-label translate>admin.2fa.enforce-for</mat-label>
                      <mat-select formControlName="type">
                        <mat-option *ngFor="let type of notificationTargetConfigTypes" [value]="type">
                          {{ notificationTargetConfigTypeInfoMap.get(type).name | translate }}
                        </mat-option>
                      </mat-select>
                    </mat-form-field>
                    <section class="tb-form-panel no-padding no-border" *ngIf="twoFaFormGroup.get('enforcedUsersFilter.type').value === notificationTargetConfigType.TENANT_ADMINISTRATORS">
                      <div class="flex flex-1 items-center justify-center">
                        <tb-toggle-select class="tb-notification-tenant-group" appearance="fill"
                                          formControlName="filterByTenants">
                          <tb-toggle-option [value]="true">{{ 'tenant.tenant' | translate }}</tb-toggle-option>
                          <tb-toggle-option [value]="false">{{ 'tenant-profile.tenant-profile' | translate }}</tb-toggle-option>
                        </tb-toggle-select>
                      </div>
                      <ng-container *ngIf="twoFaFormGroup.get('enforcedUsersFilter.filterByTenants').value; else tenantProfiles">
                        <tb-entity-list
                          formControlName="tenantsIds"
                          subscriptSizing="dynamic"
                          appearance="outline"
                          labelText="{{ 'tenant.tenants' | translate }}"
                          placeholderText="{{ 'tenant.tenants' | translate }}"
                          hint="{{ 'notification.tenants-list-rule-hint' | translate }}"
                          [entityType]="entityType.TENANT">
                        </tb-entity-list>
                      </ng-container>
                      <ng-template #tenantProfiles>
                        <tb-entity-list
                          formControlName="tenantProfilesIds"
                          subscriptSizing="dynamic"
                          appearance="outline"
                          labelText="{{ 'tenant-profile.tenant-profiles' | translate }}"
                          placeholderText="{{ 'tenant-profile.tenant-profiles' | translate }}"
                          hint="{{ 'notification.tenant-profiles-list-rule-hint' | translate }}"
                          [entityType]="entityType.TENANT_PROFILE">
                        </tb-entity-list>
                      </ng-template>
                    </section>
                  </section>
                </ng-template>
              </mat-expansion-panel>
            </div>

            <section class="tb-form-panel stroked" formArrayName="providers">
              <div class="tb-form-panel-title" translate>admin.2fa.available-providers</div>
              <ng-container *ngFor="let provider of providersForm.controls; let i = index; trackBy: trackByElement">
                  <div class="tb-form-panel stroked tb-slide-toggle">
                    <mat-expansion-panel class="tb-settings" [formGroupName]="i">
                      <mat-expansion-panel-header>
                        <mat-panel-title>
                          <mat-slide-toggle class="mat-slide flex items-center justify-start"
                            (mousedown)="toggleExtensionPanel($event, i, provider.get('enable').value)"
                            formControlName="enable">
                            {{ twoFactorAuthProvidersData.get(provider.value.providerType).name | translate }}
                          </mat-slide-toggle>
                        </mat-panel-title>
                      </mat-expansion-panel-header>

                      <ng-template matExpansionPanelContent>
                        <ng-container [ngSwitch]="provider.get('providerType').value">
                          <ng-container *ngSwitchCase="twoFactorAuthProviderType.TOTP">
                            <mat-form-field class="mat-block flex-1" appearance="outline" subscriptSizing="dynamic">
                              <mat-label translate>admin.2fa.issuer-name</mat-label>
                              <input matInput formControlName="issuerName" required>
                              <mat-error *ngIf="provider.get('issuerName').hasError('required') ||
                                                provider.get('issuerName').hasError('pattern')">
                                {{ "admin.2fa.issuer-name-required" | translate }}
                              </mat-error>
                            </mat-form-field>
                          </ng-container>
                          <div *ngSwitchCase="twoFactorAuthProviderType.SMS"
                               >
                            <mat-form-field class="mat-block flex-1" appearance="outline">
                              <mat-label translate>admin.2fa.verification-message-template</mat-label>
                              <input matInput formControlName="smsVerificationMessageTemplate" required>
                              <mat-error *ngIf="provider.get('smsVerificationMessageTemplate').hasError('required')">
                                {{ "admin.2fa.verification-message-template-required" | translate }}
                              </mat-error>
                              <mat-error *ngIf="provider.get('smsVerificationMessageTemplate').hasError('pattern')">
                                {{ "admin.2fa.verification-message-template-pattern" | translate }}
                              </mat-error>
                            </mat-form-field>
                            <tb-time-unit-input
                              appearance="outline"
                              subscriptSizing="dynamic"
                              required
                              labelText="{{ 'admin.2fa.verification-code-lifetime' | translate }}"
                              requiredText="{{ 'admin.2fa.verification-code-lifetime-required' | translate }}"
                              minErrorText="{{ 'admin.2fa.verification-code-lifetime-pattern' | translate }}"
                              [minTime]="1"
                              formControlName="verificationCodeLifetime">
                            </tb-time-unit-input>
                          </div>
                          <div *ngSwitchCase="twoFactorAuthProviderType.EMAIL">
                            <tb-time-unit-input
                              appearance="outline"
                              subscriptSizing="dynamic"
                              required
                              labelText="{{ 'admin.2fa.verification-code-lifetime' | translate }}"
                              requiredText="{{ 'admin.2fa.verification-code-lifetime-required' | translate }}"
                              minErrorText="{{ 'admin.2fa.verification-code-lifetime-pattern' | translate }}"
                              [minTime]="1"
                              formControlName="verificationCodeLifetime">
                            </tb-time-unit-input>
                          </div>
                          <div *ngSwitchCase="twoFactorAuthProviderType.BACKUP_CODE">
                            <mat-form-field class="mat-block flex-1" appearance="outline" subscriptSizing="dynamic">
                              <mat-label translate>admin.2fa.number-of-codes</mat-label>
                              <input matInput formControlName="codesQuantity" type="number" step="1" min="1" required>
                              <mat-error *ngIf="provider.get('codesQuantity').hasError('required')">
                                {{ "admin.2fa.number-of-codes-required" | translate }}
                              </mat-error>
                              <mat-error *ngIf="provider.get('codesQuantity').hasError('min') ||
                                                provider.get('codesQuantity').hasError('pattern')">
                                {{ "admin.2fa.number-of-codes-pattern" | translate }}
                              </mat-error>
                            </mat-form-field>
                          </div>
                        </ng-container>
                      </ng-template>
                    </mat-expansion-panel>
                  </div>
              </ng-container>
            </section>
            <section class="tb-form-panel stroked mb-4">
              <div class="tb-form-panel-title" translate>admin.2fa.verification-limitations</div>
              <div class="tb-form-panel no-gap no-border no-padding">
                <div class="input-row flex flex-col">
                  <tb-time-unit-input
                    appearance="outline"
                    required
                    labelText="{{ 'admin.2fa.total-allowed-time-for-verification' | translate }}"
                    requiredText="{{ 'admin.2fa.total-allowed-time-for-verification-required' | translate }}"
                    minErrorText="{{ 'admin.2fa.total-allowed-time-for-verification-pattern' | translate }}"
                    [minTime]="60"
                    formControlName="totalAllowedTimeForVerification">
                  </tb-time-unit-input>
                  <tb-time-unit-input
                    appearance="outline"
                    required
                    labelText="{{ 'admin.2fa.retry-verification-code-period' | translate }}"
                    requiredText="{{ 'admin.2fa.retry-verification-code-period-required' | translate }}"
                    minErrorText="{{ 'admin.2fa.retry-verification-code-period-pattern' | translate }}"
                    [minTime]="5"
                    formControlName="minVerificationCodeSendPeriod">
                  </tb-time-unit-input>
                  <mat-form-field class="mat-block flex-1" appearance="outline">
                    <mat-label translate>admin.2fa.max-verification-failures-before-user-lockout</mat-label>
                    <input matInput formControlName="maxVerificationFailuresBeforeUserLockout" type="number" step="1" min="0" max="65535">
                    <mat-error *ngIf="twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('pattern')
                      || twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('min')
                      || twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('max')">
                      {{ 'admin.2fa.max-verification-failures-before-user-lockout-pattern' | translate }}
                    </mat-error>
                  </mat-form-field>
                </div>
                <div class="tb-form-panel stroked tb-slide-toggle">
                  <mat-expansion-panel class="tb-settings">
                    <mat-expansion-panel-header>
                      <mat-panel-title>
                        <mat-slide-toggle class="mat-slide flex items-center justify-start" (mousedown)="toggleExtensionPanel($event, providersForm.length, twoFaFormGroup.get('verificationCodeCheckRateLimitEnable').value)"
                                          formControlName="verificationCodeCheckRateLimitEnable">
                          {{ 'admin.2fa.verification-code-check-rate-limit' | translate }}
                        </mat-slide-toggle>
                      </mat-panel-title>
                    </mat-expansion-panel-header>
                    <ng-template matExpansionPanelContent>
                      <div class="flex flex-col">
                        <mat-form-field class="mat-block flex-1" appearance="outline">
                          <mat-label translate>admin.2fa.number-of-checking-attempts</mat-label>
                          <input matInput formControlName="verificationCodeCheckRateLimitNumber" required type="number" step="1" min="1">
                          <mat-error *ngIf="twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('required')">
                            {{ 'admin.2fa.number-of-checking-attempts-required' | translate }}
                          </mat-error>
                          <mat-error *ngIf="twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('pattern')
                        || twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('min')">
                            {{ 'admin.2fa.number-of-checking-attempts-pattern' | translate }}
                          </mat-error>
                        </mat-form-field>
                        <tb-time-unit-input
                          appearance="outline"
                          subscriptSizing="dynamic"
                          required
                          labelText="{{ 'admin.2fa.within-time' | translate }}"
                          requiredText="{{ 'admin.2fa.within-time-required' | translate }}"
                          minErrorText="{{ 'admin.2fa.within-time-pattern' | translate }}"
                          [minTime]="1"
                          formControlName="verificationCodeCheckRateLimitTime">
                        </tb-time-unit-input>
                      </div>
                    </ng-template>
                  </mat-expansion-panel>
                </div>
              </div>
            </section>
          </div>
          <div class="flex flex-row items-center justify-end gap-2">
            <button mat-button mat-raised-button color="primary"
                    [disabled]="(isLoading$ | async) || twoFaFormGroup.invalid || !twoFaFormGroup.dirty"
                    type="submit">
              {{'action.save' | translate}}
            </button>
          </div>
        </fieldset>
      </form>
    </mat-card-content>
  </mat-card>
</div>
